﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;

namespace Miao.Editor
{


    public class NamespaceRenameToolPro : global::UnityEditor.EditorWindow
    {
        private NamespaceReplacementConfig config;
        private Vector2 scrollPosition;
        private bool showPreview = false;
        private Dictionary<string, List<string>> previewResults = new Dictionary<string, List<string>>();
        private SerializedObject serializedConfig;

        [MenuItem("Miao/Namespace Rename Tool Pro")]
        public static void ShowWindow()
        {
            GetWindow<NamespaceRenameToolPro>("命名空间替换工具");
        }

        private void OnEnable()
        {
            LoadConfig();
        }
        private void OnDisable()
        {

            EditorUtility.SetDirty(config);
            AssetDatabase.SaveAssets();
        }
        private void LoadConfig()
        {
            string configPath = "Assets/Editor/NamespaceReplacementConfig.asset";
            config = AssetDatabase.LoadAssetAtPath<NamespaceReplacementConfig>(configPath);
            
            if (config == null)
            {
                config = CreateInstance<NamespaceReplacementConfig>();
                if (!Directory.Exists("Assets/Editor"))
                {
                    Directory.CreateDirectory("Assets/Editor");
                }
                AssetDatabase.CreateAsset(config, configPath);
                AssetDatabase.SaveAssets();
            }
            
            // 初始化序列化对象
            serializedConfig = new SerializedObject(config);
        }

        private void OnGUI()
        {
            if (serializedConfig == null)
            {
                LoadConfig();
                return;
            }
            
            serializedConfig.Update();
            
            scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition);

            EditorGUILayout.LabelField("命名空间替换配置", EditorStyles.boldLabel);
            EditorGUILayout.Space();

            // 直接显示整个配置对象的序列化面板
            EditorGUILayout.PropertyField(serializedConfig.FindProperty("targetFolder"), new GUIContent("目标文件夹"));
            
            // 添加文件夹选择按钮
            EditorGUILayout.BeginHorizontal();
            GUILayout.Space(EditorGUIUtility.labelWidth);
            if (GUILayout.Button("选择文件夹", GUILayout.Width(100)))
            {
                string currentPath = serializedConfig.FindProperty("targetFolder").stringValue;
                string defaultPath = Application.dataPath;
                
                if (!string.IsNullOrEmpty(currentPath))
                {
                    if (currentPath.StartsWith("Assets"))
                    {
                        defaultPath = Path.Combine(Application.dataPath, currentPath.Substring(6));
                    }
                    else if (Directory.Exists(currentPath))
                    {
                        defaultPath = currentPath;
                    }
                }
                
                string selectedPath = EditorUtility.OpenFolderPanel("选择目录", defaultPath, "");
                if (!string.IsNullOrEmpty(selectedPath) && selectedPath.StartsWith(Application.dataPath))
                {
                    serializedConfig.FindProperty("targetFolder").stringValue = "Assets" + selectedPath.Substring(Application.dataPath.Length);
                }
            }
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.PropertyField(serializedConfig.FindProperty("previewOnly"), new GUIContent("仅预览"));
            EditorGUILayout.PropertyField(serializedConfig.FindProperty("replacements"), new GUIContent("替换规则"), true);

            EditorGUILayout.Space();

            // 显示路径状态
            string targetPath = serializedConfig.FindProperty("targetFolder").stringValue;
            if (targetPath.StartsWith("Assets"))
            {
                targetPath = Path.Combine(Application.dataPath, targetPath.Substring(6));
            }
            
            bool pathExists = Directory.Exists(targetPath);
            Color originalColor = GUI.color;
            GUI.color = pathExists ? Color.green : Color.red;
            EditorGUILayout.LabelField($"路径状态: {(pathExists ? "有效" : "无效")}", EditorStyles.miniLabel);
            GUI.color = originalColor;
            
            // 显示文件数量
            if (pathExists)
            {
                int fileCount = 0;
                try
                {
                    fileCount = Directory.GetFiles(targetPath, "*.cs", SearchOption.AllDirectories).Length;
                }
                catch (Exception ex)
                {
                    fileCount = -1;
                }
                
                if (fileCount >= 0)
                {
                    EditorGUILayout.LabelField($"找到 {fileCount} 个 C# 文件", EditorStyles.miniLabel);
                }
                else
                {
                    EditorGUILayout.LabelField("无法统计文件数量", EditorStyles.miniLabel);
                }
            }

            EditorGUILayout.Space();

            // 操作按钮
            EditorGUILayout.BeginHorizontal();
            
            if (GUILayout.Button("预览替换"))
            {
                PreviewReplacements();
                showPreview = true;
            }
            
            if (GUILayout.Button("执行替换"))
            {
                if (EditorUtility.DisplayDialog("确认替换", 
                    "这将修改所有匹配的文件。确定要继续吗？", "确定", "取消"))
                {
                    ExecuteReplacements();
                }
            }
            
            EditorGUILayout.EndHorizontal();

            // 预览结果
            if (showPreview && previewResults.Count > 0)
            {
                EditorGUILayout.Space();
                EditorGUILayout.LabelField("预览结果", EditorStyles.boldLabel);
                
                foreach (var kvp in previewResults)
                {
                    EditorGUILayout.LabelField($"文件: {kvp.Key}", EditorStyles.boldLabel);
                    foreach (var change in kvp.Value)
                    {
                        EditorGUILayout.LabelField($"  {change}", EditorStyles.miniLabel);
                    }
                    EditorGUILayout.Space();
                }
            }

            EditorGUILayout.EndScrollView();
            
            serializedConfig.ApplyModifiedProperties();
        }

        private void PreviewReplacements()
        {
            previewResults.Clear();
            
            if (serializedConfig.FindProperty("replacements").arraySize == 0)
            {
                EditorUtility.DisplayDialog("错误", "请先添加替换规则", "确定");
                return;
            }
            
            foreach (string file in GetTargetFiles())
            {
                //if (Path.GetExtension(file).ToLower() == ".cs")
                {
                    List<string> changes = new List<string>();
                    string content = File.ReadAllText(file);
                    string originalContent = content;

                    for (int i = 0; i < serializedConfig.FindProperty("replacements").arraySize; i++)
                    {
                        var replacementElement = serializedConfig.FindProperty("replacements").GetArrayElementAtIndex(i);
                        var oldNamespace = replacementElement.FindPropertyRelative("oldNamespace").stringValue;
                        var newNamespace = replacementElement.FindPropertyRelative("newNamespace").stringValue;
                        
                        var replacement = new NamespaceReplacement
                        {
                            oldNamespace = oldNamespace,
                            newNamespace = newNamespace
                        };
                        
                        content = ApplyReplacements(content, replacement, changes);
                    }

                    if (content != originalContent)
                    {
                        previewResults[file] = changes;
                    }
                }
            }
        }

        private void ExecuteReplacements()
        {
            if (serializedConfig.FindProperty("replacements").arraySize == 0)
            {
                EditorUtility.DisplayDialog("错误", "请先添加替换规则", "确定");
                return;
            }
            int modifiedFiles = 0;

            foreach (string file in GetTargetFiles())
            {
                    string content = File.ReadAllText(file);
                    string originalContent = content;

                    for (int i = 0; i < serializedConfig.FindProperty("replacements").arraySize; i++)
                    {
                        var replacementElement = serializedConfig.FindProperty("replacements").GetArrayElementAtIndex(i);
                        var oldNamespace = replacementElement.FindPropertyRelative("oldNamespace").stringValue;
                        var newNamespace = replacementElement.FindPropertyRelative("newNamespace").stringValue;
                        
                        var replacement = new NamespaceReplacement
                        {
                            oldNamespace = oldNamespace,
                            newNamespace = newNamespace
                        };
                        
                        content = ApplyReplacements(content, replacement, null);
                    }

                    if (content != originalContent)
                    {
                        File.WriteAllText(file, content, Encoding.UTF8);
                        modifiedFiles++;
                    }
            }

            AssetDatabase.Refresh();
            EditorUtility.DisplayDialog("完成", $"已修改 {modifiedFiles} 个文件", "确定");
        }

        private IEnumerable<string> GetTargetFiles()
        {
            string targetPath = serializedConfig.FindProperty("targetFolder").stringValue;
            var searchB = Directory.GetFiles(targetPath, "*.test", SearchOption.AllDirectories);
            var searchA = Directory.GetFiles(targetPath, "*.cs", SearchOption.AllDirectories);

            foreach (var file in searchB)
            {
                yield return file;
            }

            foreach (var file in searchA)
            {
                yield return file;
            }

            // 检查路径是否存在

            
        }

        /// <summary>
        /// 应用命名空间替换规则到代码内容
        /// 按顺序执行以下替换操作，确保所有可能的命名空间引用都被正确处理
        /// </summary>
        /// <param name="content">要处理的代码内容</param>
        /// <param name="replacement">命名空间替换配置</param>
        /// <param name="changes">记录变更的列表（可选）</param>
        /// <returns>替换后的代码内容</returns>
        private string ApplyReplacements(string content, NamespaceReplacement replacement, List<string> changes)
        {
            string oldNs = replacement.oldNamespace;
            string newNs = replacement.newNamespace;

            // 1. 替换 using 语句
            // 匹配: using winS.UnityEditor.UIElement;
            // 替换为: using Miao.Editor.UIElement;
            content = ReplaceUsingStatements(content, oldNs, newNs, changes);

            // 2. 替换命名空间声明
            // 匹配: namespace winS.UnityEditor.UIElement {
            // 替换为: namespace Miao.Editor.UIElement {
            content = ReplaceNamespaceDeclarations(content, oldNs, newNs, changes);

            // 3. 替换别名指令
            // 匹配: using Button = winS.UnityEditor.UIElement.Button;
            // 替换为: using Button = Miao.Editor.UIElement.Button;
            content = ReplaceAliasDirectives(content, oldNs, newNs, changes);

            // 4. 替换完全限定名称（在代码中的直接引用）
            // 匹配: Button button = new winS.UnityEditor.UIElement.Button();
            // 替换为: Button button = new Miao.Editor.UIElement.Button();
            content = ReplaceFullyQualifiedNames(content, oldNs, newNs, changes);

            // 5. 替换泛型类型参数中的命名空间
            // 匹配: List<winS.UnityEditor.UIElement.Button> buttons;
            // 替换为: List<Miao.Editor.UIElement.Button> buttons;
            content = ReplaceGenericTypeParameters(content, oldNs, newNs, changes);

            // 6. 替换 typeof 和 nameof 表达式
            // 匹配: typeof(winS.UnityEditor.UIElement.Button) 或 nameof(winS.UnityEditor.UIElement.Button)
            // 替换为: typeof(Miao.Editor.UIElement.Button) 或 nameof(Miao.Editor.UIElement.Button)
            content = ReplaceTypeExpressions(content, oldNs, newNs, changes);

            // 7. 替换特性中的类型引用
            // 匹配: [CustomEditor(typeof(winS.UnityEditor.UIElement.Button))]
            // 替换为: [CustomEditor(typeof(Miao.Editor.UIElement.Button))]
            content = ReplaceAttributeTypeReferences(content, oldNs, newNs, changes);

            // 8. 替换 XML 文档注释中的命名空间引用
            // 匹配: /// <param name="button">winS.UnityEditor.UIElement.Button 实例</param>
            // 替换为: /// <param name="button">Miao.Editor.UIElement.Button 实例</param>
            content = ReplaceXmlDocumentation(content, oldNs, newNs, changes);

            // 9. 替换 using static 指令
            // 匹配: using static winS.UnityEditor.UIElement.Constants;
            // 替换为: using static Miao.Editor.UIElement.Constants;
            content = ReplaceUsingStaticDirectives(content, oldNs, newNs, changes);

            return content;
        }

        private string ReplaceUsingStatements(string content, string oldNs, string newNs, List<string> changes)
        {
            // 匹配 using 语句
            string pattern = $@"using\s+{Regex.Escape(oldNs)}\s*;";
            string replacement = $"using {newNs};";
            
            int count = Regex.Matches(content, pattern).Count;
            if (count > 0)
            {
                changes?.Add($"替换 {count} 个 using 语句: {oldNs} -> {newNs}");
            }
            
            return Regex.Replace(content, pattern, replacement);
        }

        private string ReplaceNamespaceDeclarations(string content, string oldNs, string newNs, List<string> changes)
        {
            // 匹配命名空间声明，保留原始的换行符和空格
            string pattern = $@"(namespace\s+){Regex.Escape(oldNs)}(\s*{{)";
            string replacement = $"$1{newNs}$2";

            int count = Regex.Matches(content, pattern).Count;
            if (count > 0)
            {
                changes?.Add($"替换 {count} 个命名空间声明: {oldNs} -> {newNs}");
            }

            return Regex.Replace(content, pattern, replacement);
        }

        private string ReplaceAliasDirectives(string content, string oldNs, string newNs, List<string> changes)
        {
            // 匹配别名指令 - 修复：匹配完整的别名定义，包括类型名称
            // 支持简单的类型名称和泛型类型名称
            string pattern = $@"using\s+(\w+)\s*=\s*{Regex.Escape(oldNs)}\.([^;]+)\s*;";
            string replacement = $"using $1 = {newNs}.$2;";
            
            int count = Regex.Matches(content, pattern).Count;
            if (count > 0)
            {
                changes?.Add($"替换 {count} 个别名指令: {oldNs} -> {newNs}");
            }
            
            return Regex.Replace(content, pattern, replacement);
        }

        private string ReplaceFullyQualifiedNames(string content, string oldNs, string newNs, List<string> changes)
        {
            // 匹配完全限定名称（不在 using 语句和别名指令中）使用更简单但更可靠的负向后查找
            string pattern = $@"(?<!using\s+)(?<!=\s*){Regex.Escape(oldNs)}\.";
            string replacement = $"{newNs}.";
            
            int count = Regex.Matches(content, pattern).Count;
            if (count > 0)
            {
                changes?.Add($"替换 {count} 个完全限定名称: {oldNs} -> {newNs}");
            }
            
            return Regex.Replace(content, pattern, replacement);
        }

        private string ReplaceGenericTypeParameters(string content, string oldNs, string newNs, List<string> changes)
        {
            // 匹配泛型类型参数中的命名空间
            string pattern = $@"<[^>]*{Regex.Escape(oldNs)}\.";
            string replacement = $"<{newNs}.";
            
            int count = Regex.Matches(content, pattern).Count;
            if (count > 0)
            {
                changes?.Add($"替换 {count} 个泛型类型参数: {oldNs} -> {newNs}");
            }
            
            return Regex.Replace(content, pattern, replacement);
        }

        private string ReplaceTypeExpressions(string content, string oldNs, string newNs, List<string> changes)
        {
            // 匹配 typeof 和 nameof 表达式
            string pattern = $@"(typeof|nameof)\s*\(\s*{Regex.Escape(oldNs)}\.";
            string replacement = $"$1({newNs}.";
            
            int count = Regex.Matches(content, pattern).Count;
            if (count > 0)
            {
                changes?.Add($"替换 {count} 个类型表达式: {oldNs} -> {newNs}");
            }
            
            return Regex.Replace(content, pattern, replacement);
        }

        private string ReplaceAttributeTypeReferences(string content, string oldNs, string newNs, List<string> changes)
        {
            // 匹配特性中的类型引用
            string pattern = $@"typeof\s*\(\s*{Regex.Escape(oldNs)}\.";
            string replacement = $"typeof({newNs}.";
            
            int count = Regex.Matches(content, pattern).Count;
            if (count > 0)
            {
                changes?.Add($"替换 {count} 个特性类型引用: {oldNs} -> {newNs}");
            }
            
            return Regex.Replace(content, pattern, replacement);
        }

        private string ReplaceXmlDocumentation(string content, string oldNs, string newNs, List<string> changes)
        {
            // 匹配 XML 文档注释中的命名空间引用
            string pattern = $@"(///\s*<[^>]*>.*?){Regex.Escape(oldNs)}\.";
            string replacement = $"$1{newNs}.";
            
            int count = Regex.Matches(content, pattern).Count;
            if (count > 0)
            {
                changes?.Add($"替换 {count} 个 XML 文档注释: {oldNs} -> {newNs}");
            }
            
            return Regex.Replace(content, pattern, replacement);
        }

        private string ReplaceUsingStaticDirectives(string content, string oldNs, string newNs, List<string> changes)
        {
            // 匹配 using static 指令
            string pattern = $@"using\s+static\s+{Regex.Escape(oldNs)}\.";
            string replacement = $"using static {newNs}.";
            
            int count = Regex.Matches(content, pattern).Count;
            if (count > 0)
            {
                changes?.Add($"替换 {count} 个 using static 指令: {oldNs} -> {newNs}");
            }
            
            return Regex.Replace(content, pattern, replacement);
        }
    }
}

